import { isUndefined, isNull, getTSFromPb, emtpyToUndefined, toString } from "mmb";
import * as user_pv_logpb from "../grpc-client/service/user_pv_log_pb";
import {
  getBgsUserPvLogOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import { UserPvLog, CreateUserPvLogParams, UpdateUserPvLogParams } from "./declareTypes"
import { getPub, makeTopicOfPub, wrapToMessage } from "../proxy/nsqProxy";

/****************************************************************************************/
/*                                   user_pv_log entity                                 */
/****************************************************************************************/

const topicOfAddUserPvLog = "add-user_pv_log";

const userPvLogPbToObject = (pb: user_pv_logpb.UserPvLogEntity): UserPvLog => {
  return {
    userPvLogId: `${pb.getId()}`,
    created: getTSFromPb(
      pb.getCreated()!.getSeconds(),
      pb.getCreated()!.getNanos()
    ),
    userId: `${pb.getUserId()}`,
    brandId: emtpyToUndefined(toString(pb.getBrandId())),
    shareUserId: emtpyToUndefined(toString(pb.getShareUserId())),
    page: pb.getPage(),
  };
};

/****************************************************************************************/
/*                                   user_pv_log cmd                                    */
/****************************************************************************************/
export const createUserPvLogMq = async ({
  userId,
  brandId,
  shareUserId,
  page,
}: CreateUserPvLogParams): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const topic = makeTopicOfPub(topicOfAddUserPvLog)
    const msg = wrapToMessage({
      userId: Number(userId),
      brandId: Number(brandId),
      shareUserId: Number(shareUserId),
      page,
    })
    // console.log('publish createUserPvLogMq =>', topic ,JSON.stringify(msg))
    getPub().publish(
      topic,
      msg,
      (err) => {
        if (err) {
          // console.log("createUserPvLogMq err", err);
          reject(false);
        }
        // console.log("createUserPvLogMq success");
        resolve(true);
      }
    );
  });
};

export const createUserPvLog = async ({
  userId,
  brandId,
  shareUserId,
  page,
}: CreateUserPvLogParams): Promise<UserPvLog> => {
  const cl = getBgsUserPvLogOpSafely();
  const req = new user_pv_logpb.CreateUserPvLogRequest();

  req.setUserId(Number(userId));
  if (!isUndefined(brandId)) {
    req.setBrandId(Number(brandId));
  }
  if (!isUndefined(shareUserId)) {
    req.setShareUserId(Number(shareUserId));
  }
  req.setPage(page);

  return new Promise((resolve, reject) => {
    cl.createUserPvLog(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(userPvLogPbToObject(res.getUserPvLog()!));
    });
  });
};

export const updateUserPvLog = async ({
  userPvLogId,
  isCounted,
}: UpdateUserPvLogParams): Promise<UserPvLog> => {
  const cl = getBgsUserPvLogOpSafely();
  const req = new user_pv_logpb.UpdateUserPvLogRequest();

  req.setId(Number(userPvLogId));
  req.setIsCounted(isCounted);

  return new Promise((resolve, reject) => {
    cl.updateUserPvLog(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(userPvLogPbToObject(res.getUserPvLog()!));
    });
  });
};

/****************************************************************************************/
/*                                   user_pv_log query                                  */
/****************************************************************************************/

export const getLatestUserPvLogByUserID = async (
  userId: string
): Promise<UserPvLog> => {
  const cl = getBgsUserPvLogOpSafely();
  const req = new user_pv_logpb.GetLatestUserPvLogByUserIdRequest();

  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getLatestUserPvLogByUserId(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(userPvLogPbToObject(res.getUserPvLog()!));
      }
    );
  });
};

export interface GetLatestUserPvLogByUserIDWithBrandIDParams {
  userId: string;
  brandId?: string;
}

export const getLatestUserPvLogByUserIDWithBrandID = async ({
  userId,
  brandId,
}: GetLatestUserPvLogByUserIDWithBrandIDParams): Promise<UserPvLog> => {
  const cl = getBgsUserPvLogOpSafely();
  const req = new user_pv_logpb.GetLatestUserPvLogByUserIdWithBrandIdRequest();

  req.setUserId(Number(userId));
  if (!isUndefined(brandId)) {
    req.setBrandId(Number(brandId));
  }

  return new Promise((resolve, reject) => {
    cl.getLatestUserPvLogByUserIdWithBrandId(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(userPvLogPbToObject(res.getUserPvLog()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   user_pv_log aggs query                             */
/****************************************************************************************/

export interface AggsToUserRecentNews {
  userId: string;
  latestTime: number;
}

const aggsToUserRecentNewsPbToObject = (pb: user_pv_logpb.AggsToUserRecentNewsEntity): AggsToUserRecentNews => {
  return {
    userId: `${pb.getUserId()}`,
    latestTime: getTSFromPb(
      pb.getLatestTime()!.getSeconds(),
      pb.getLatestTime()!.getNanos()
    ),
  };
};

export const listAggsToUserRecentNewses = async (
  userIds: string[]
): Promise<AggsToUserRecentNews[]> => {
  const cl = getBgsUserPvLogOpSafely();
  const req = new user_pv_logpb.ListAggsToUserRecentNewsesByUserIDsRequest();

  req.setUserIdsList(userIds.map(u => Number(u)));

  return new Promise((resolve, reject) => {
    cl.listAggsToUserRecentNewsesByUserIDs(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      
      resolve(res.getAggsToUserRecentNewsesList().map(it => aggsToUserRecentNewsPbToObject(it)));
    });
  });
};